using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.SharePoint;
using System.Text.RegularExpressions;
using System.Globalization;

namespace TST.SharePoint.Shared
{
    public class WSSFieldCalculated : FieldCalculated, IDataFormatting
    {
        private SPFieldCalculated _field;

        /// <summary>
        /// Constructor.
        /// </summary>
        public WSSFieldCalculated()
        {
        }

        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="ID">The ID for the field.</param>
        public WSSFieldCalculated(string Id)
            : base(Id)
        {
        }

        public WSSFieldCalculated(SPFieldCalculated field)
            : base(field.Id.ToString())
        {
            _field = field;
        }

        public int CurrencyLocaleId
        {
            get
            {
                if (_field != null)
                    return _field.CurrencyLocaleId;
                return 0;
            }
        }

        public override object GetTypedValue(object value)
        {
            if (value == null || _field==null)
                return null;
            string stringValue = value.ToString();
            if (stringValue.IndexOf(";#") > 0)
                stringValue = stringValue.Substring(stringValue.IndexOf(";#")+2);
            switch (_field.OutputType)
            {
                case SPFieldType.Text:
                    return stringValue;
                case SPFieldType.DateTime:
                    DateTime dateTime;
                    if (DateTime.TryParse(stringValue.ToString(), out dateTime))
                        return dateTime;
                    return null;
                case SPFieldType.Boolean:
                    return ((!string.IsNullOrEmpty(stringValue.ToString())) && (stringValue.ToString() == "1"));
                case SPFieldType.Number:
                case SPFieldType.Currency:
                    double result;
                    if (double.TryParse(stringValue.ToString(), System.Globalization.NumberStyles.Any, new CultureInfo(1033), out result))
                        return result;
                    return null;
                default:
                    return stringValue;
            }
        }

        public override string GetTypedValueFormatted(object value)
        {
            if (value == null || _field == null)
                return null;
            string stringValue = value.ToString();
            if (stringValue.IndexOf(";#") > 0)
                stringValue = stringValue.Substring(stringValue.IndexOf(";#") + 2);
            IDataFormatting formatting = this as IDataFormatting;
            if (formatting != null)
            {
                string format = formatting.DataFormatString;
                if (format.IndexOf(":") > 0)
                {
                    format = formatting.DataFormatString.Substring(format.IndexOf(":") + 1);
                    format = format.Replace("}", string.Empty);
                }
                switch (_field.OutputType)
                {
                    case SPFieldType.DateTime:
                        DateTime dateTime;
                        if (DateTime.TryParse(stringValue.ToString(),new CultureInfo(1033), DateTimeStyles.None, out dateTime))
                            return dateTime.ToString(format, new CultureInfo(CurrencyLocaleId));
                        break;
                    case SPFieldType.Boolean:
                        bool boolResult = ((!string.IsNullOrEmpty(stringValue.ToString())) && (stringValue.ToString() == "1"));
                        return boolResult.ToString(new CultureInfo(CurrencyLocaleId));
                    case SPFieldType.Number:
                    case SPFieldType.Currency:
                        double result;
                        if (double.TryParse(stringValue.ToString(), System.Globalization.NumberStyles.Any, new CultureInfo(1033), out result))
                        {
                            return result.ToString(format, new CultureInfo(CurrencyLocaleId));
                        }
                        break;
                    default:
                        if (value.ToString().ToLower() == "float;#0")
                            return null;
                        else
                            return stringValue.ToString();
                }
            }
            return stringValue.ToString();
        }

        public override string GetTypedValueAsString(object value)
        {
            if (value == null || _field == null)
                return null;
            string stringValue = value.ToString();
            if (stringValue.IndexOf(";#") > 0)
                stringValue = stringValue.Substring(stringValue.IndexOf(";#") + 2);
            IDataFormatting formatting = this as IDataFormatting;
            if (formatting != null)
            {
                switch (_field.OutputType)
                {
                    case SPFieldType.DateTime:
                        DateTime dateTime;
                        if (DateTime.TryParse(stringValue.ToString(), new CultureInfo(1033), DateTimeStyles.None, out dateTime))
                            return dateTime.ToString(new CultureInfo(1033));
                        break;
                    case SPFieldType.Boolean:
                        bool boolResult = ((!string.IsNullOrEmpty(stringValue.ToString())) && (stringValue.ToString() == "1"));
                        if (boolResult)
                            return "1";
                        return "0";
                    case SPFieldType.Number:
                    case SPFieldType.Currency:
                        double result;
                        if (double.TryParse(stringValue.ToString(), System.Globalization.NumberStyles.Any, new CultureInfo(1033), out result))
                            return result.ToString(new CultureInfo(1033));
                        break;
                    default:
                        if (value.ToString().ToLower() == "float;#0")
                            return null;
                        else
                            return stringValue.ToString();
                }
            }
            return stringValue.ToString();
        }

        /// <summary>
        /// Get the Result FieldType for the calculated field.
        /// </summary>
        /// <returns></returns>
        public override FieldType OutputFieldType
        {
            get
            {
                if (_field == null)
                    return FieldType.String;
                switch (_field.OutputType)
                {
                    case SPFieldType.Text:
                        return FieldType.String;
                    case SPFieldType.DateTime:
                        return FieldType.DateTime;
                    case SPFieldType.Boolean:
                        return FieldType.Boolean;
                    case SPFieldType.Number:
                        return FieldType.Number;
                    case SPFieldType.Currency:
                        return FieldType.Currency;
                }
                return FieldType.String;
            }
        }

        /// <summary>
        /// Get the .NET datatype. 
        /// </summary>
        public override Type DataType
        {
            get
            {
                switch (_field.OutputType)
                {
                    case SPFieldType.DateTime:
                        return typeof(DateTime);
                    case SPFieldType.Boolean:
                        return typeof(Boolean);
                    case SPFieldType.Number:
                    case SPFieldType.Currency:
                        return typeof(double);
                }
                return typeof(string);
            }
        }

        public override FilterType FilterType
        {
            get
            {
                switch (_field.OutputType)
                {
                    case SPFieldType.DateTime:
                        return FilterType.DateTime; ;
                    case SPFieldType.Boolean:
                        return FilterType.Boolean;
                    case SPFieldType.Number:
                        return FilterType.Number; ;
                    case SPFieldType.Currency:
                        return FilterType.Currency;
                    case SPFieldType.Text:
                        return FilterType.Text;
                }
                return FilterType.Unknown;
            }
        }

        internal override string GetFilterValue(string value)
        {
            switch (_field.OutputType)
            {
                case SPFieldType.DateTime:
                    DateTime date;
                    if (DateTime.TryParse(value, out date))
                        return FieldDateTime.CreateISO8601DateStringFromSystemDateString(date);
                    return string.Empty;
            }
            return value;
        }


        #region IDataFormatting Members

        public string DataFormatString
        {
            get
            {
                if (_field == null)
                    return string.Empty;

                switch (_field.OutputType)
                {
                    case SPFieldType.DateTime:
                        if (_field.DateFormat == SPDateTimeFieldFormatType.DateTime)
                            return "{0:g}";
                        else
                            return "{0:d}";
                    case SPFieldType.Currency:
                        return WSSFieldCurrency.GetFormatString(_field.DisplayFormat);
                    case SPFieldType.Number:
                        return WSSFieldNumber.GetFormatString(_field.ShowAsPercentage, _field.DisplayFormat);
                }
                return string.Empty;
            }
        }

        #endregion
    }
}
